﻿// //   Copyright 2007-2011 Comdiv (F. Sadykov) - http://code.google.com/u/fagim.sadykov/
// //   Supported by Media Technology LTD 
// //    
// //   Licensed under the Apache License, Version 2.0 (the "License");
// //   you may not use this file except in compliance with the License.
// //   You may obtain a copy of the License at
// //    
// //        http://www.apache.org/licenses/LICENSE-2.0
// //    
// //   Unless required by applicable law or agreed to in writing, software
// //   distributed under the License is distributed on an "AS IS" BASIS,
// //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// //   See the License for the specific language governing permissions and
// //   limitations under the License.
// //   
// //   MODIFICATIONS HAVE BEEN MADE TO THIS FILE
using System.Collections.Generic;
using System.Xml;
using System.Xml.Linq;

namespace Comdiv.UXmlDiff {
	/// <summary>
	/// class to iterate and annotate XObjects, optimized to wide 
	/// logic with no iteration throw already changed items
	/// </summary>
	public class XDiffSelector {
		private readonly XElement element;
		private XObject[] currentSelection;
		private bool safemode;

		public XDiffSelector(XElement element, bool safemode = false) {
			this.element = element;
			this.safemode = safemode;
		}


		public XObject[] GetNext() {
			if (null == currentSelection) {
				currentSelection = new[] {element};
				element.Diff(safemode);
				return currentSelection;
			}
			var newlist = new List<XObject>();
			foreach (var o in currentSelection) {
				//attributes and texts cannot be processed to down level
				if (o.NodeType == XmlNodeType.Attribute) continue;
				if (o.NodeType == XmlNodeType.Text) continue;
				//we need node to be annotated
				var annotation = o.Diff(safemode);
				// if something was happend to element we think that we do not need to procees it down
				if (annotation.Type != XDiffAnnotationType.Equal && annotation.Type!=XDiffAnnotationType.None) continue;
				// if something was annotated but it's not XElement we do not know what to do and how it can be
				if (!(o is XElement)) throw new XDiffException("innormal node type for diff in ");
				// get one level down
				foreach (var obj in ((XElement) o).Attributes()) {
					obj.Diff(safemode);
					newlist.Add(obj);
				}
				foreach (var obj in ((XElement) o).Nodes()) {
					if (obj.NodeType == XmlNodeType.Element || obj.NodeType == XmlNodeType.Text) {
						obj.Diff(safemode);
						newlist.Add(obj);
					}
				}
			}
			return currentSelection = newlist.ToArray();
		}
	}
}